package net.lab1024.sa.admin.module.business.outbound.service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import net.lab1024.sa.admin.module.business.cutting.dao.CuttingInfoDao;
import net.lab1024.sa.admin.module.business.cutting.domain.entity.CuttingInfoEntity;
import net.lab1024.sa.admin.module.business.outbound.dao.OutboundInfoDao;
import net.lab1024.sa.admin.module.business.outbound.dao.OutboundItemDao;
import net.lab1024.sa.admin.module.business.outbound.domain.entity.OutboundInfoEntity;
import net.lab1024.sa.admin.module.business.outbound.domain.entity.OutboundItemEntity;
import net.lab1024.sa.admin.module.business.outbound.domain.form.OutboundInfoAddForm;
import net.lab1024.sa.admin.module.business.outbound.domain.form.OutboundInfoQueryForm;
import net.lab1024.sa.admin.module.business.outbound.domain.form.OutboundInfoUpdateForm;
import net.lab1024.sa.admin.module.business.outbound.domain.vo.OutboundInfoVO;
import net.lab1024.sa.admin.module.business.outbound.domain.vo.OutboundItemVO;
import net.lab1024.sa.admin.module.business.template.domain.entity.QuotationTemplateItemsEntity;
import net.lab1024.sa.admin.util.ExcelUtils;
import net.lab1024.sa.base.common.code.UserErrorCode;
import net.lab1024.sa.base.common.util.SmartBeanUtil;
import net.lab1024.sa.base.common.util.SmartPageUtil;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.domain.PageResult;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.lab1024.sa.base.common.util.SmartRequestUtil;
import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum;
import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService;
import net.lab1024.sa.base.module.support.serialnumber.constant.SerialNumberIdEnum;
import net.lab1024.sa.base.module.support.serialnumber.service.SerialNumberService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import jakarta.annotation.Resource;

import javax.xml.crypto.Data;

/**
 * 出库单 Service
 *
 * @Author zzx
 * @Date 2025-08-13 15:17:33
 * @Copyright zzx
 */

@Service
public class OutboundInfoService {

    @Resource
    private OutboundInfoDao outboundInfoDao;
    @Resource
    private OutboundItemDao outboundItemDao;
    @Resource
    private DataTracerService dataTracerService;
    @Resource
    private SerialNumberService serialNumberService;
    @Resource
    private CuttingInfoDao cuttingInfoDao;

    /**
     * 分页查询
     */
    public PageResult<OutboundInfoVO> queryPage(OutboundInfoQueryForm queryForm) {
        Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
        List<OutboundInfoVO> list = outboundInfoDao.queryPage(page, queryForm);
        return SmartPageUtil.convert2PageResult(page, list);
    }

    /**
     * 添加
     */
    public ResponseDTO<String> add(OutboundInfoAddForm addForm) {
        if (addForm.getCuttingId() == null) {
            return ResponseDTO.error(UserErrorCode.DATA_CUSTOM, "下料id不能为空");
        }
        if (addForm.getList().isEmpty()) {
            return ResponseDTO.error(UserErrorCode.DATA_CUSTOM, "出库明细不能为空");
        }
        QueryWrapper<OutboundInfoEntity> queryWrapper = new QueryWrapper<>();
        OutboundInfoEntity entity = new OutboundInfoEntity();
        entity.setCuttingId(addForm.getCuttingId());
        entity.setOutboundComplete(1);
        entity.setDisabledFlag(0);
        entity.setDeletedFlag(0);
        queryWrapper.setEntity(entity);
        boolean exists = outboundInfoDao.exists(queryWrapper);
        if (exists) {
            return ResponseDTO.error(UserErrorCode.DATA_CUSTOM, "已出库完成的下料单无法重复出库");
        }
        CuttingInfoEntity cuttingInfo = cuttingInfoDao.selectById(entity.getCuttingId());
        if (cuttingInfo == null) {
            return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST, "数据不存在");
        }
        Long userId = SmartRequestUtil.getRequestUserId();

        // 出库完成
        if (entity.getOutboundComplete() == 1) {
            CuttingInfoEntity newCuttingInfo = SmartBeanUtil.copy(entity, CuttingInfoEntity.class);
            newCuttingInfo.setUpdateUserId(userId);
            newCuttingInfo.setCompleteTime(LocalDateTime.now());
            newCuttingInfo.setUpdateTime(null);
            newCuttingInfo.setStatus(1);
            cuttingInfoDao.updateById(newCuttingInfo);
            dataTracerService.update(cuttingInfo.getCuttingId(), DataTracerTypeEnum.CUTTING,
                    cuttingInfo, newCuttingInfo);
        }
        OutboundInfoEntity outboundInfoEntity = SmartBeanUtil.copy(addForm, OutboundInfoEntity.class);
        outboundInfoEntity.setDisabledFlag(0);
        outboundInfoEntity.setCreateUserId(userId);
        outboundInfoEntity.setUpdateUserId(userId);
        outboundInfoEntity.setOutboundDateId(serialNumberService.generate(SerialNumberIdEnum.OUTBOUND));
        outboundInfoDao.insert(outboundInfoEntity);
        dataTracerService.insert(outboundInfoEntity.getOutboundId(), DataTracerTypeEnum.OUTBOUND);
        List<OutboundItemEntity> list = SmartBeanUtil.copyList(addForm.getList(), OutboundItemEntity.class);
        for (int i = 0; i < list.size(); i++) {
            OutboundItemEntity item = list.get(i);
            item.setSerialNumber(i+1);
            item.setCreateUserId(userId);
            item.setDisabledFlag(0);
            item.setUpdateUserId(userId);
            item.setOutboundId(outboundInfoEntity.getOutboundId());
            outboundItemDao.insert(item);
            dataTracerService.insert(item.getOutboundItemId(), DataTracerTypeEnum.QUOTATION_ITEM);
        }
        return ResponseDTO.ok();
    }

    /**
     * 更新
     *
     */
    public ResponseDTO<String> update(OutboundInfoUpdateForm updateForm) {
        if (updateForm.getList().isEmpty()) {
            return ResponseDTO.error(UserErrorCode.DATA_CUSTOM, "出库明细不能为空");
        }
        Long userId = SmartRequestUtil.getRequestUserId();
        OutboundInfoEntity oldOut = outboundInfoDao.selectById(updateForm.getOutboundId());
        if (oldOut == null) { return ResponseDTO.error(UserErrorCode.DATA_EMPTY); }
        OutboundInfoEntity outboundInfoEntity = SmartBeanUtil.copy(updateForm, OutboundInfoEntity.class);
        outboundInfoEntity.setUpdateUserId(userId);
        outboundInfoDao.updateById(outboundInfoEntity);
        dataTracerService.update(outboundInfoEntity.getOutboundId(), DataTracerTypeEnum.OUTBOUND, oldOut, outboundInfoEntity);
        List<OutboundItemEntity> items = SmartBeanUtil.copyList(updateForm.getList(), OutboundItemEntity.class);
        for (int i = 0; i < items.size(); i++) {
            items.get(i).setSerialNumber(i+1);
            items.get(i).setUpdateUserId(userId);
        }
        List<OutboundItemEntity> oldEntities = SmartBeanUtil.copyList(outboundInfoDao.queryItemsById(outboundInfoEntity.getOutboundId()),
                OutboundItemEntity.class);
        List<OutboundItemEntity> newEntities = items.stream().filter(item -> item.getOutboundItemId() == null).toList();
        List<OutboundItemEntity> updateEntities = items.stream().filter(item -> item.getOutboundItemId() != null).toList();
        if (!newEntities.isEmpty()) {
            newEntities.forEach(item -> {
                item.setCreateUserId(userId);
                outboundItemDao.insert(item);
                dataTracerService.insert(item.getOutboundItemId(), DataTracerTypeEnum.OUTBOUND_ITEM);
            });
        }

        if (!oldEntities.isEmpty()) {
            Map<Long, OutboundItemEntity> map = updateEntities.stream().collect(Collectors.toMap(OutboundItemEntity::getOutboundItemId, item -> item));
            oldEntities.forEach(old -> {
                OutboundItemEntity update = map.get(old.getOutboundId());
                if (update == null) { // 删除
                    update = SmartBeanUtil.copy(old, OutboundItemEntity.class);
                    update.setDeletedFlag(1);
                }
                update.setUpdateUserId(userId);
                outboundItemDao.updateById(update);
                dataTracerService.update(update.getOutboundItemId(), DataTracerTypeEnum.OUTBOUND_ITEM, old, update);
            });
        }
        return ResponseDTO.ok();
    }

    /**
     * 批量删除
     */
    public ResponseDTO<String> batchDelete(List<Long> idList) {
        if (CollectionUtils.isEmpty(idList)){
            return ResponseDTO.ok();
        }
        outboundInfoDao.batchUpdateDeleted(idList, true);
        return ResponseDTO.ok();
    }

    /**
     * 单个删除
     */
    public ResponseDTO<String> delete(Long outboundId) {
        if (null == outboundId){
            return ResponseDTO.ok();
        }
        outboundInfoDao.updateDeleted(outboundId, true);
        return ResponseDTO.ok();
    }

    public ResponseDTO<OutboundInfoVO> detail(Long outboundId) {
        if (null == outboundId){
            return ResponseDTO.error(UserErrorCode.DATA_CUSTOM, "数据不能为空");
        }
        OutboundInfoEntity outboundInfoEntity = outboundInfoDao.selectById(outboundId);
        if (outboundInfoEntity == null){
            return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST, "数据不存在");
        }
        OutboundInfoVO vo =  SmartBeanUtil.copy(outboundInfoEntity, OutboundInfoVO.class);
        List<OutboundItemVO> list = outboundInfoDao.queryItemsById(outboundId);
        if (list.isEmpty()){
            return ResponseDTO.error(UserErrorCode.DATA_EMPTY, "数据不能为空");
        }
        vo.setList(list);
        return ResponseDTO.ok(vo);
    }

    public ResponseDTO<String> exportExcl(Long outboundId) {
        OutboundInfoVO details = outboundInfoDao.getDetails(outboundId);
        if (details == null){
            return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST, "数据不存在");
        }
        List<OutboundItemVO> list = outboundInfoDao.queryItemsById(outboundId);
        if (list.isEmpty()){
            return ResponseDTO.error(UserErrorCode.DATA_EMPTY, "数据不能为空");
        }
        details.setList(list);
        String path = ExcelUtils.exportOutboundInfoExcel(details);
        return ResponseDTO.ok(path);
    }
}
